#ifndef __ASTRAL_API_H_
#define __ASTRAL_API_H_

#include "astraldef.h"



/*****************************************************************************/
/**                                Task API                                 **/
/*****************************************************************************/

/**
 * @brief Create a task object
 * 
 * @param task The control block of task.
 * @param sp_bot The kernel stack bottom pointer.
 * @param byte_size The size of stack.
 * @param entry The entry function.
 *
 * @note ---sp_bot--->>>>>>---sp_top----
 * @note sp_top = sp_bot + byte_size
 * 
 * @details sp_top and sp_bot will auto aligned to word size.
 */
// void create_task(AstralTask task, StackPointer sp_bot, int byte_size, runable entry, int priority, const char* name);
void create_task(AstralTask task,
                    AstralAttr attr,
                    runable entry,
                    object arg);
boolean distach_task(AstralTask task);
void yeild_task();
void suspend_task(AstralTask task);
void resume_task(AstralTask task);
AstralTask get_curr_task();
const char* get_task_status(AstralTask t);
void list_thread();

void pool_dispatch_job(AstralTaskPool pool, runable job, object arg);
AstralTaskPool create_task_pool(const char *name, int nr_thread, int prio);


/*****************************************************************************/
/**                                Sync API                                 **/
/*****************************************************************************/
void create_mutex(AstralMutex mutex);
boolean obtain_mutex(AstralMutex mutex);
boolean release_mutex(AstralMutex mutex);

void create_sem(AstralSem sem);
boolean obtain_sem(AstralSem sem);
boolean release_sem(AstralSem sem);

boolean spin_lock(AstralSpin lock);
boolean spin_unlock(AstralSpin lock);
word spin_lock_irq(AstralSpin lock);
boolean spin_unlock_irq(AstralSpin lock, word irq_status);


/*****************************************************************************/
/**                                 UI API                                  **/
/*****************************************************************************/

/**
 * @brief kernel log output
 * 
 * @param fmt format string for output
 * @param ... detail paramters
 */
void kprint(const char *fmt, ...) __CHECK__PRINTF_FORMAT__;
void kerror(const char *fmt, ...) __CHECK__PRINTF_FORMAT__;
void kscan(char *stream);
void flush_kstdout();
void list_irqs();


/*****************************************************************************/
/**                                 Device API                              **/
/*****************************************************************************/

AstralDevice open_device(const char* name);
int write_device_char(object dev, char c);
char read_device_char(object dev);
int close_device(object dev);
boolean register_device(AstralDevice dev, AstralDevInfo info);
void list_device();

/*****************************************************************************/
/**                                 Driver API                              **/
/*****************************************************************************/
u32 allocate_dynamic_mid();
boolean register_driver(u32 mid, AstralDriver driver);
void list_driver();

#define STATIC_REGISTER_DRIVER(probe) \
    __attribute__((__used__))         \
    __attribute__((section("sdrv"))) static executable do_##probe \
    = CAST_AS(executable, probe);

/*****************************************************************************/
/**                                 Timer API                               **/
/*****************************************************************************/
void create_ttimer(AstralTickTimer timer, int timeout, executable callback, object arg);
void set_ttimer_attribute(AstralTickTimer timer, boolean auto_reload, const char *name);
boolean start_ttimer(AstralTickTimer timer);
boolean stop_ttimer(AstralTickTimer timer);
u64 get_tick_count();


/**
 * @brief register irq and enable irq
 *
 * @param id irq id
 * @param target the core who will handle this irq, natural number id
 * @param callback the handle function for this irq
 * @param arg the argument passed to the handle function
 * @param usage hint
 * @return boolean 
 */
boolean register_int(int id, int target, runable callback, object arg, const char* usage);

#endif//__ASTRAL_API_H_